package code.homework;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author cc
 * @create 2023-03-01  22:26
 */
public class SnakeGame {

    /**
     * 输入：
     * ["SnakeGame", "move", "move", "move", "move", "move", "move"]
     * [[3, 2, [[1, 2], [0, 1]]], ["R"], ["D"], ["R"], ["U"], ["L"], ["U"]]
     * 输出：
     * [null, 0, 0, 1, 1, 2, -1]
     *
     * 来源：力扣（LeetCode）
     * 链接：https://leetcode.cn/problems/design-snake-game
     * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
     */


     LinkedList<Location> snake =  new LinkedList<>();
     // 蛇尾 temp坐标，用于保存上次移动的蛇尾坐标，以便于发生吃果实事件的后身体+1的操作
     Location snakeTailTemp;

     int width = 0;
     int height = 0;
     int[][] food;
     boolean isEnd = false;
     int foodIndex = 0;

    public SnakeGame(int width, int height, int[][] food) {
        this.width = width;
        this.height = height;
        this.food = food;
    }


    public int move(String direction) {
        if(isEnd){
            return -1;
        }
        if(snake.size() == 0){
            snake.add(new Location(0,0));
        }
        Location snakeHead = snake.peekFirst();
        //以下需要深拷贝
        Location snakeTail = new Location(snake.peekLast().x, snake.peekLast().y);
        List<Location> snakeBody = snake.subList(0, snake.size()-1).stream().map(o->new Location(o.x, o.y)).collect(Collectors.toList());

        if(direction.equals("R")){
            snakeHead.x = snakeHead.x +1;
        }
        if(direction.equals("L")){
            snakeHead.x = snakeHead.x -1;
        }
        if(direction.equals("U")){
            snakeHead.y = snakeHead.y -1;
        }
        if(direction.equals("D")){
            snakeHead.y = snakeHead.y +1;
        }
        snake = new LinkedList<>();
        snake.addAll(snakeBody);
        snake.addFirst(snakeHead);
        if(!collisionDetection()){
            isEnd = true;
            return -1;
        }
        snakeTailTemp = snakeTail;
        if(foodIndex < food.length){
            if(eat(food[foodIndex])){
                foodIndex ++;
            }
        }
        return snake.size() -1;
    }

    /**
     * 碰撞检测
     * @return false：撞了
     */
    public boolean collisionDetection(){
        Location snakeHead = snake.peekFirst();
        //x 轴越界
        if(snakeHead.x <0 || snakeHead.x >= width){
            return false;
        }
        //y 轴越界
        if(snakeHead.y < 0 || snakeHead.y >= height){
            return false;
        }
        if(snake.size() != 1){
            // 蛇头坐标与身体不重复
            List<Location> snakeBody = snake.subList(1, snake.size());
            long count = snakeBody.stream().filter(body -> snakeHead.x == body.x && snakeHead.y == body.y).count();
            if(count > 0){
                return false;
            }
        }
        return true;
    }

    /**
     * 吃食物
     */
    public boolean eat(int[] food){
        Location snakeHead = snake.get(0);
        if(food[1] == snakeHead.x && food[0] == snakeHead.y ){
            snake.add(snakeTailTemp);
            return true;
        }
        return false;
    }

    class Location{
        int x;
        int y;
        Location(int x,int y){
            this.x = x;
            this.y = y;
        }
    }
}
